/**
 * PHOSIDE: PHosphorylation Site IDentification Engine.
 * Copyright 2009 Digital Biology Lab, University of Missouri.
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 3 of the License, or (at your option) any later
 * version. <p/> This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more
 * details.
 */

package phoside;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 *
 * @author gjj
 */
public interface PhosphoProteins extends Proteins {

    public enum PhosphoType {
        SER ('S', "Serine"),
        THR ('T', "Threonine"),
        TYR ('Y', "Tyrosine"),
        HIS ('H', "Histidine"),
        ASP ('D', "Aspartic");

        private static final long serialVersionUID = 369134939176105077L;

        private final char aatype;
        private final String fullName;

        PhosphoType(final char aatype, final String fullName) {
            this.aatype = aatype;
            this.fullName = fullName;
        }

        public char aatype() {
            return aatype;
        }

        public String fullName() {
            return fullName;
        }

        public boolean matches(char aa) {
            return (aa==aatype) || (aa==Character.toLowerCase(aa));
        }

        public String toString() {
            return fullName()+" ("+aatype+")";
        }

        static public PhosphoType valueOfByAA(char aa) {
            switch (aa) {
                case 'S':
                case 's':
                    return SER;
                case 'T':
                case 't':
                    return THR;
                case 'Y':
                case 'y':
                    return TYR;
                case 'H':
                case 'h':
                    return HIS;
                case 'D':
                case 'd':
                    return ASP;
                default:
                    return null;
            }
        }
        
        static public Set<Character> phosphorylatableAminoAcids() {
            return phosphorylatableAminoAcids(PhosphoType.values());
        }

        static public Set<Character> phosphorylatableAminoAcids(Set<PhosphoType> allowTypes) {
            if (allowTypes==null)
                return phosphorylatableAminoAcids();
            return phosphorylatableAminoAcids(allowTypes.toArray(new PhosphoType[0]));
        }

        static public Set<Character> phosphorylatableAminoAcids(PhosphoType[] allowTypes) {
            if (allowTypes==null)
                return phosphorylatableAminoAcids();
            Set<Character> set = new HashSet<Character>();
            for (PhosphoType type : allowTypes) {
                char c = type.aatype();
                set.add(c);
                set.add(Character.toLowerCase(c));
            }

            return set;
        }
    }

    /**
     *
     * @param proteinAccession
     * @return phosphosites as index (start from 0)
     * @throws NullPointerException if proteinAccession is null
     */
    public Set<Integer> getSites(String proteinAccession);

    /**
     *
     * @param proteinAccession
     * @param site
     * @return
     */
    public List<String> getSiteNotes(String proteinAccession, int site);

    /**
     *
     * @param ProteinAccession
     * @param site
     * @throws NullPointerException if proteinAccession is null
     * @throws IndexOutOfRangeException if location is either less than 1 or
     *         greater than the length of the protein
     * @throws IllegalStateException if the sites is not S/T/Y
     * @throws IllegalStateException if ProteinAccession not exist
     */
    public void addSite(String proteinAccession, int site);

    /**
     *
     * @param ProteinAccession
     * @param site
     * @param notes
     * @throws NullPointerException if proteinAccession is null
     * @throws IndexOutOfRangeException if location is either less than 1 or
     *         greater than the length of the protein
     * @throws IllegalStateException if the sites is not S/T/Y
     * @throws IllegalStateException if ProteinAccession not exist
     */
    public void addSite(String proteinAccession, int site, List<String> notes);

    /**
     *
     * @param proteinAccession
     * @param sites
     * @throws NullPointerException if proteinAccession is null
     * @throws IndexOutOfRangeException if location is either less than 1 or
     *         greater than the length of the protein
     * @throws IllegalStateException if the sites is not S/T/Y
     * @throws IllegalStateException if ProteinAccession not exist
     */
    public void addSites(String proteinAccession, Set<Integer> sites);

    /**
     * 
     * @param proteinAccession
     * @param sites
     */
    public void removeSites(String proteinAccession, Set<Integer> sites);

    /**
     * 
     * @param proteinAccession
     */
    public void clearSites(String proteinAccession);
}
